/*
 * server_connection_0.c
 *
 *  Created on: 2012-5-2
 *      Author: jawinton
 */


#include "../apue.h"
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <syslog.h>

#define BUFLEN 128
#define QLEN 10

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

extern int initserver (int, const struct sockaddr *, socklen_t, int);

void serve (int sockfd) {
	int clfd, status;
	pid_t pid;
	//FILE *fp;
	//char buf[BUFLEN];

	while(1) {
		clfd = accept(sockfd, NULL, NULL);
		if (clfd < 0) {
			syslog(LOG_ERR, "ruptimed: accept error: %s", strerror(errno));
			exit(1);
		}

		if ((pid = fork()) < 0) {
			syslog(LOG_ERR, "ruptimed: fork error: %s", strerror(errno));
			exit(1);
		} else if(pid == 0) {
			if (dup2(clfd, STDOUT_FILENO) != STDOUT_FILENO || dup2(clfd, STDERR_FILENO) != STDERR_FILENO) {
				syslog(LOG_ERR, "ruptimed: unexpected error: %s", strerror(errno));
				exit(1);
			}
			close(clfd);
			execl("/usr/bin/uptime", "uptime", (char *)0);
			syslog(LOG_ERR, "ruptimed: unexpected return from exec: %s", strerror(errno));
		} else {
			close(clfd);
			waitpid(pid, &status, 0);
		}


		/*if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
			sprintf(buf, "error: %s\n",strerror(errno));
			send(clfd, buf, strlen(buf), 0);
		} else {
			while (fgets(buf, BUFLEN, fp) != NULL)
				send(clfd, buf, strlen(buf), 0);
			pclose(fp);
		}
		close(clfd);*/
	}
}

int main (int argc, char *argv[]) {
	struct addrinfo *ailist, *aip;
	struct addrinfo hint;
	int sockfd, err, n;
	char *host;
	pid_t pid;

	if (argc != 1) err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
	n = sysconf(_SC_HOST_NAME_MAX);
	if (n < 0)
#endif
		n = HOST_NAME_MAX;
	host = malloc(n);
	if (host == NULL) err_sys("malloc error");
	if (gethostname(host, n) < 0) err_sys("gethostname error");
	daemonize("ruptimed");
	hint.ai_addr = NULL;
	hint.ai_addrlen = 0;
	hint.ai_canonname = NULL;
	hint.ai_family = 0;
	hint.ai_flags = AI_CANONNAME;
	hint.ai_next = NULL;
	hint.ai_protocol = 0;
	hint.ai_socktype = SOCK_STREAM;
	if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
	//if ((err = getaddrinfo(host, NULL, &hint, &ailist)) != 0) {
		syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s", gai_strerror(err));
		exit(1);
	}
#if 0
	for (aip = ailist; aip != NULL; aip = aip->ai_next) {
		syslog(LOG_DAEMON,"%s: %d\n", aip->ai_canonname, pid);
	}
#endif
	for (aip = ailist; aip != NULL; aip = aip->ai_next) {
		if ((sockfd = initserver(aip->ai_addr, aip->ai_addrlen, aip->ai_socktype, aip->ai_protocol, QLEN)) >= 0) {
			if ((pid = fork()) < 0) {
				syslog(LOG_ERR, "ruptimed: fork error: %s", strerror(errno));
				exit(1);
			} else if (pid == 0) {
				serve(sockfd);
				exit(0);
			} else {
				syslog(LOG_DAEMON,"%s: %d\n", aip->ai_canonname, pid);
			}
		}
	}

	exit(1);
}
